package tripmaker
package output

import eventos._
import movimientos._
import Moneda._
import BigDecimal.RoundingMode.{ HALF_UP => HalfUp }
import org.joda.time.format.DateTimeFormat
import scala.xml.dtd.DocType
import scala.xml.dtd.PublicID
import java.io.File
import tripmaker.Viaje.Resumen

object HTML {
  var OutputDir = "output"
  var ResourcesDir = "resources"
  var MonedaLocal = UYU
    
  trait ToHTML[T] {
    def toHTML(t: T): xml.NodeSeq
  }
  implicit object ActividadToHTML extends ToHTML[Actividad] { def toHTML(t: Actividad) = HTML.toHTML(t) }
  implicit object EventoToHTML extends ToHTML[Evento] { def toHTML(t: Evento) = HTML.toHTML(t) }
  
  val PageBreak = <p style="page-break-before: always;"/>
    
  def toHTML(viaje: Viaje): xml.Node = wrap(viaje.nombre, portada(viaje) ++ PageBreak ++ diasHTML(viaje))
  
  def wrap(title: String, html: Seq[xml.NodeSeq]) = <html><body><head><link href={ResourcesDir + "/style.css"} rel="stylesheet" type="text/css"/><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>{ title }</title></head>{ html }</body></html>
  
  def diasHTML(viaje: Viaje): Seq[xml.NodeSeq] = resumen(viaje) ++ PageBreak ++ { viaje.diasCompletos map { d => toHTML(d, viaje.costoFuturo(d)) ++ PageBreak } } ++ (if(viaje.diasCompletos.size + 1 % 2 == 0) Seq(emptyPage) else Nil)
  
  def emptyPage: xml.NodeSeq = <br/> ++ PageBreak
  
  def diasHTMLFull(viaje: Viaje): Seq[xml.NodeSeq] = diasHTML(viaje) flatMap { d => Seq(d, emptyPage) }
  
  def paginasA(viaje: Viaje): Seq[xml.NodeSeq] = {
    val dias = diasHTMLFull(viaje)
    assert(dias.size % 2 == 0)
    val lastIndex = dias.size - 1
    val mid = lastIndex/2
    (for {
      (d1ind, d2ind) <- (0 to mid by 2).zip(lastIndex to mid by -2)
      d1 = dias(d1ind)
      d2 = dias(d2ind)
    } yield Seq(d1,d2)).flatten
  }
  
  def paginasB(viaje: Viaje): Seq[xml.NodeSeq] = {
    val dias = diasHTMLFull(viaje)
    assert(dias.size % 2 == 0)
    val lastIndex = dias.size - 1
    val mid = lastIndex/2 + 1
    Seq(emptyPage, emptyPage) ++ 
    (for {
      (d1ind, d2ind) <- (lastIndex - 1 to mid by -2).zip(1 to mid by 2)
      d1 = dias(d1ind)
      d2 = dias(d2ind)
    } yield Seq(d1,d2)).flatten
  }
  
  def toHTML(d: Día, costoFuturo: Monto): xml.Node = {
    import d._
    val terr = territorio getOrElse Territorio.NingunLado
    
    <table class="global">
      <tr>
        <td class="cabezalCont">
          <table class="cabezal">
            <tr>
              <td>
    			<span class="fechaDia"><span class="diaFechaDia">{ día.getOrElse("-") }</span>{ "/" + mes.getOrElse("-") + "/" + año.getOrElse("-") }</span>
    		  </td>
              <td class="altitudCabezal">{ terr.altitud } msnm</td>
            </tr>
            <tr>
              <td colspan="2">Arrancamos en <span class="lugarCabezal">{ terr.nombre }</span>, <span class="paisCabezal">{ terr.país.nombre }</span></td>
            </tr>
            <tr class="cabezal2doNivel">
              <td colspan="2">GMT <span class="gmtCabezal">{ terr.gmt }</span>, Moneda <span class="monedaCabezal">{ terr.país.moneda.id }</span></td>
            </tr>
            <tr class="cabezal3erNivel">
              <td colspan="2">
                <span>1 { terr.país.moneda.id } in { MonedaLocal.id }</span><span class="tcUYUCabezal">{ terr.país.moneda.tc(MonedaLocal).setScale(2, HalfUp) }</span>,
                <span>1 USD in { terr.país.moneda.id }</span><span class="tcUSDCabezal">{ terr.país.moneda.tcUSDinv.setScale(2, HalfUp) }</span>
              </td>
            </tr>
            <tr class="cabezal3erNivel">
              <td style="white-space: nowrap;">Costo planificado</td>
              <td width="100%">
                {
	                var sep = ""
	                costos map { c => 
	                  val psep = sep
	                  sep = "+"
	                  xml.Text(psep) +: <span class="monto">{ c.toString }</span> 
	                }  
                }, futuro<span class="monto">{ costoFuturo.toString }</span>
              </td>
            </tr>
            <tr class="cabezal3erNivel">
              <td style="white-space: nowrap;">Costo real</td>
              <td width="100%"><span class="montoInput">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td>
            </tr>
          </table>
        </td>
      </tr>
      <tr>
        <td class="planificacion">
          <table>
            <tr>
              <th class="cabezalEventos">Eventos planificados</th>
              <th class="cabezalActividades">Actividades posibles</th>
            </tr>
            <tr>
              <td class="eventos">{ toHTML(eventos) }</td>
              <td class="actividades">{ toHTML(actividades) }</td>
            </tr>
          </table>
        </td>
      </tr>
    </table>
  }

  def toHTML[T](elems: Seq[T])(implicit h: ToHTML[T]): xml.Node = 
  	<table>
  	{elems filter { e => h.toHTML(e).nonEmpty } map { e => <tr><td>{h.toHTML(e)}</td></tr> }}
  	</table>
  
  val fmt = DateTimeFormat.forPattern("HH:mm")
  
  def toHTML(e: Evento): xml.NodeSeq = e match {
    case e: Llegada => 
      <span class="horaEvento">{fmt.print(e.horario)}</span>
	  <img class="flechaLlegada" src={ ResourcesDir + "/flecha-llegada.gif" } />
	  <span class="lugarEvento">{e.a}</span>
	  <span class="sitioEvento">{e.lugar}</span>
    case e: Salida => 
      <span class="horaEvento">{fmt.print(e.horario)}</span>
      <img class="flechaSalida" src={ ResourcesDir + "/flecha-salida.gif" }/>
      <span class="lugarEvento">{e.desde}</span>
      <span class="sitioEvento">{e.lugar}</span>
      <span class="empresaEvento">{e.medio}</span>
      <span class="monto">{ if (e.costo.valor == 0) "ya pagado" else e.costo}</span>
    case e: CruceFrontera => <table class="cruceFrontera"><tr><td></td></tr></table>
	case e: HitoPago => 
      <table class="hito">
    	<tr><td>
		<span class="bulletHito">&#9633;</span>
		<span class="textoHito">{e.texto.head}</span>
		{if (e.costo.valor != 0) <span class="monto">{e.costo}</span>}
		{e.texto.tail map { l => <span class="textoHito complemento">{l}</span> }}
	    </td></tr>
	  </table>
	case e: CambiarPlata => 
      <table class="hito">
    	<tr><td>
		<span class="bulletHito">&#9633;</span>
		<span class="textoHito">{e.texto.head}</span>
		<span class="monto">{e.cantidad}</span>
		{e.texto.tail map { l => <span class="textoHito complemento">{l}</span> }}
	    </td></tr>
	  </table>
    case e: Hito => <table class="hito"><tr><td><span class="bulletHito">&#9633;</span>{e.texto.zipWithIndex map { l => <span class={if(l._2 != 0) "textoHito complemento" else "textoHito"}>{l._1}</span> }}</td></tr></table>
    case e: Difuso => 
      <table class="difuso">
	    <tr><td>{e.texto.zipWithIndex map { l => <span class={if(l._2 != 0) "complemento" else null}>{l._1}</span> }}
	    {if (e.costo.valor != 0) <span class="monto">{e.costo}</span>}</td></tr></table>
    case _ => Nil
  }
  
  def toHTML(actividad: Actividad): xml.Node =
    <table class="actividad"><tr><td><span class="bulletActividad">&#9679;</span> {actividad.texto.zipWithIndex map { l => <span class={if(l._2 != 0) "textoActividad complemento" else "textoActividad"} >{l._1}</span> }}</td></tr></table>

  def portada(viaje: Viaje): xml.Node = {
    import viaje._
    val pag = 
      <table class="global">
    	<tr>
			<td class="titulo">
				<h1>{ nombre }</h1>
				<h2 class="territorios">{ territorios mkString " - " }</h2>
				<h3>{ diaInicial.dayOfMonth.get + "/" + diaInicial.monthOfYear.get + "/" + diaInicial.year.get }</h3>
			</td>
		</tr>
		<tr>
			<td class="logoCont">
				<img class="logo" src={ResourcesDir + "/" + viaje.logo} />
			</td>
		</tr>
	  </table>
				
    wrap(viaje.nombre, emptyPage ++ pag)
  }

  def toHTML(resumen: Resumen): xml.Node = {
    import resumen._
    
    <span class="resumen">
	<h1>Resumen { pais }</h1>
    <h2>costo: { costo }</h2>
    <h2>costo moneda local: { costoLocal } ( { costoLocal.in(USD) } )</h2>
    <h2>costo moneda extranjera: { costoExtranjero }</h2>
    </span>
  } 
    
  
  def resumen(viaje: Viaje): xml.Node = {
    import viaje._
    <table class="global"><tr><td>{ <h1>Costo total: { costoTotal }</h1> }</td></tr>{ paises map total map { r => <tr><td>{ toHTML(r) }</td></tr> } }</table>
  }

  
  
  def write(viaje: Viaje) {
    println("Generando html %s...".format(viaje.nombre))
    
    write(toHTML(viaje), viaje, "")
  }
  
  def write(html: xml.Node, viaje: Viaje, sufijo: String) = {
    val fileName = OutputDir + "/" + viaje.nombre + sufijo + ".html"
    println(fileName)
    val doctype = DocType("html", PublicID("-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"), Nil)
    
    val pp = new scala.xml.PrettyPrinter(80, 2)
    
    val writer = new java.io.FileWriter(fileName)
    try {
      writer.write(doctype.toString + "\n")
      writer.write(pp.format(html))
    } finally {
      writer.close()
    }
    
    fileName
  }
}